<?php

namespace App\Repositories;

use App\Models\Bills;
use App\Models\Courier;
use App\Models\EntryTally;
use App\Models\Network;
use App\Models\NetworkExpress;
use App\Models\Order;
use App\Exceptions\GeneralException;
use App\Models\OrderInfo;
use App\Models\Service;
use App\Models\SignOutTally;
use App\Models\User;
use App\Package\Message\Message;
use Carbon\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;

class OrderRepository extends BaseRepository
{
    /**
     *  REDIS_EXPIRES_FOR_SECOND 缓存有效期一分钟
     */
    const REDIS_EXPIRES_FOR_SECOND = 60;

    /**
     *  REDIS_EXPIRES_FOR_DAY 缓存有效期一天
     */
    const REDIS_EXPIRES_FOR_DAY = 86400;

    /**
     *  REDIS_EXPIRES_FOR_DAY 缓存有效期一天
     */
    const CHARGE = 0.10;

    /**
     *  ORDER_STATUS 订单状态列表
     */
    const ORDER_STATUS = [
        '1' => '暂存',
        '2' => '配送中',
        '3' => '待取件',
        '4' => '已取件',
        '5' => '投诉中',
        '6' => '异常件',
        '7' => '已退回',
        '8' => '已退款',
    ];

    /**
     *  ORDER_TYPE 订单类型列表
     */
    const ORDER_TYPE = [
        '0' => '派送件',
        '1' => '自提件',
        '2' => '寄送件',
    ];

    public function model()
    {
        return Order::class;
    }

    /**
     * 获取订单列表
     * Date: 2018/4/26
     * @author Tenny
     * @param $courier_id
     * @param $service_id
     * @param $type
     * @param $status
     * @param $created_at
     * @param $limit
     * @param $single_number
     * @param $owner_service_id
     * @return \Illuminate\Database\Eloquent\Collection|static[]
     */
    public function getOrders($courier_id, $service_id = false, $type = false, $status = false, $created_at, $limit = 15, $single_number = false, $owner_service_id = 0)
    {
        $query = \DB::table('order as o');
        if ($courier_id !== false) {
            $query->where('o.courier_id', '=', $courier_id);
        }
        if ($service_id !== false) {
            if ($service_id == -1) {
                //获取子站点id集合
                $query1 = Service::query();
                $service_ids = $query1
                    ->select(['id'])
                    ->where('pid', '=', $owner_service_id)
                    ->get()
                    ->toArray();
                $ids = [];
                if (is_array($service_ids) && count($service_ids)) {
                    foreach ($service_ids as $service) {
                        $ids[] = $service['id'];
                    }
                }
                $ids[] = $owner_service_id;
                $query->whereIn('o.service_id', $ids);
            } else {
                $query->where('o.service_id', '=', $service_id);
            }
        }
        if ($type !== false) {
            $query->where('o.type', '=', $type);
        }
        if ($status !== false) {
            $query->where('o.status', '=', $status);
        }
        if ($created_at) {
            $query->whereBetween('o.created_at', $created_at);
        }
        if ($single_number !== false) {
            $query->where(function ($query) use ($single_number) {
                $query->where('o.single_number', 'like', '%' . $single_number)
                    ->orWhere('o.take_code', '=', $single_number)
                    ->orWhere('o.to_mobile', '=', $single_number);

            });
        }
        /**
         * 添加模糊搜索条件  把结果的手机号相关连的手机号都查询出来
         */
        $phones = $query->select('o.to_mobile')->whereNull('o.deleted_at')->get()->map(function ($item) {
            return $item->to_mobile;
        });
        if ($phones) {
            $phones = $phones->toArray();
        } else {
            $phones = [];
        }
        $query = \DB::table('order as o');
        if ($courier_id !== false) {
            $query->where('o.courier_id', '=', $courier_id);
        }
        if ($service_id !== false) {
            if ($service_id == -1) {
                //获取子站点id集合
                $query1 = Service::query();
                $service_ids = $query1
                    ->select(['id'])
                    ->where('pid', '=', $owner_service_id)
                    ->get()
                    ->toArray();
                $ids = [];
                if (is_array($service_ids) && count($service_ids)) {
                    foreach ($service_ids as $service) {
                        $ids[] = $service['id'];
                    }
                }
                $ids[] = $owner_service_id;
                $query->whereIn('o.service_id', $ids);
            } else {
                $query->where('o.service_id', '=', $service_id);
            }
        }
        if ($type !== false) {
            $query->where('o.type', '=', $type);
        }
        if ($status !== false) {
            $query->where('o.status', '=', $status);
        }
        if ($created_at) {
            $query->whereBetween('o.created_at', $created_at);
        }
        $orders = $query
            ->select(['o.id', 'o.order_id', 'o.single_number', 'o.to_mobile', 'o.type', 'o.status', 'o.take_code', 'o.status', 'o.label', 'o.created_at', 'info.region_mark', 's.designation as service_name', 'express.express_name', 'express.express_logo', 'n.designation as network_name', 'c.name as courier_name', 'c.phone as courier_phone'])
            // 获取快递公司信息
            ->leftJoin('express_company as express', 'express.id', '=', 'o.express_id')
            ->leftJoin('service as s', 'o.service_id', '=', 's.id')
            ->leftJoin('network as n', 'o.network_id', '=', 'n.id')
            ->leftJoin('courier as c', 'o.courier_id', '=', 'c.id')
            ->leftJoin('order_info as info', 'o.id', '=', 'info.order_id')
            ->whereIn('o.to_mobile', $phones)
            ->whereNull('o.deleted_at')
            ->orderBy('o.created_at', 'desc')
            ->orderBy('o.id', 'desc')
            ->paginate($limit);
        return $orders;
    }

    /**
     * 获取个人订单列表
     * Date: 2018/05/26
     * @author Tenny
     * @param $courier_id
     * @param $service_id
     * @param $type
     * @param $mold
     * @param $limit
     * @return \Illuminate\Database\Eloquent\Collection|static[]
     */
    public function getPersonalOrders($courier_id, $service_id, $type, $mold = false, $limit = 15)
    {
        $query = \DB::table('order as o');
        $query->where('o.service_id', '=', $service_id);
        /*
         *  $type    0:派送件  1:自提件   2:寄送件
         * */
        if ($type == 1) {
            $query->where('o.type', '=', 1);
        } else {
            $query->where('o.type', '!=', 1);
            $query->where('o.courier_id', '=', $courier_id);
        }
        /*
         *  $mold    1:进行中的订单  2:已完成订单  3:异常订单  默认进行中的订单
         * */
        if ($mold !== false) {
            switch ($mold) {
                case 1:
                    if ($type == 1) {
                        $query->where('o.status', '=', 3);
                    } else {
                        $query->where('o.status', '=', 2);
                    }
                    break;
                case 2:
                    $query->where('o.status', '=', 4);
                    break;
                case 3:
                    $query->where('o.status', '>=', 5);
                    $query->where('o.status', '<=', 8);
                    break;
                default:
                    $query->where('o.status', '=', 2);
            }
        }
        $orders = $query
            ->select(['o.id', 'o.order_id', 'o.single_number', 'o.to_mobile', 'o.type', 'o.status', 'o.status', 'o.label', 'o.sign_in_at', 'o.created_at', 'info.region_mark', 's.designation as service_name', 'express.express_name', 'express.express_logo'])
            // 获取快递公司信息
            ->leftJoin('express_company as express', 'express.id', '=', 'o.express_id')
            ->leftJoin('order_info as info', 'o.id', '=', 'info.order_id')
            ->leftJoin('service as s', 'o.service_id', '=', 's.id')
            ->orderBy('o.created_at', 'desc')
            ->orderBy('o.id', 'desc')
            ->paginate($limit);
        return $orders;
    }

    /**
     * 获取订单详情
     * Date: 2018/5/27
     * @author Tenny
     * @param $order_id
     * @return \Illuminate\Database\Eloquent\Collection|static[]
     */
    public function getOrderDetails($order_id)
    {
        $redis_key = sprintf('GET_ORDER_DETAILS_V1_%d', $order_id);
        if (!Redis::exists($redis_key)) {
            $query = \DB::table('order');
            $orders = $query->select(['order.*', 'info.price', 'info.price', 'info.weight', 'info.volume', 'info.calculation', 'info.courier_money', 'info.service_money', 'info.express_money', 'info.pack_money', 'info.platform_money', 'info.actual_weight', 'info.region_mark', 'service.designation as service_name', 'express.express_name', 'express.express_logo', 'net.designation as network_name', 'c.name as courier_name', 'c.phone as courier_phone'])
                // 获取订单详细信息
                ->leftJoin('order_info as info', 'order.id', '=', 'info.order_id')
                // 获取服务站信息
                ->leftJoin('service', 'order.service_id', '=', 'service.id')
                // 获取快递公司信息
                ->leftJoin('express_company as express', 'express.id', '=', 'order.express_id')
                // 获取网点信息
                ->leftJoin('network as net', 'net.id', '=', 'order.network_id')
                // 获取快递员信息
                ->leftJoin('courier as c', 'c.id', '=', 'order.courier_id')
                ->where('order.id', '=', $order_id)
                ->orderBy('id', 'desc')
                ->first();
            Redis::setex($redis_key, self::REDIS_EXPIRES_FOR_SECOND, json_encode($orders));
        } else {
            $res = Redis::get($redis_key);
            $orders = json_decode($res);
        }
        return $orders;
    }

    /**
     * 生成订单
     * Date: 2018/05/27
     * @author Tenny
     * @param $request
     * @param $type
     * @return \Illuminate\Database\Eloquent\Collection|static[]
     * @throws \App\Exceptions\GeneralException
     * @deprecated 2018/07/03
     */
    public function addOrder($request, $type = false)
    {
        $user = Auth::guard('courier')->user();
        $name = $user->name;
        $service_id = $user->service_id;
        $courier_id = $user->id;
        //判断该快递号是否已经入库
        $result = Order::where('single_number', '=', $request->single_number)
            ->where('status', '!=', 7)
            ->first();
        if ($result) {
            throw new GeneralException('该快递已入库', 400);
        }
        if ($request->single_number) {
            $result = $this->matchingNetwork($service_id, $request->single_number);
        }
        if (is_array($result) && count($result) > 0) {
            $express_id = $result['express_id'];
            $unit_price = $result['unit_price'];
            $network_id = $result['network_id'];
        } else {
            throw new GeneralException('未匹配到合作网点', 400);
        }
        $take_code = $request->take_code ? $request->take_code : null;
        if (!$take_code) {
            throw new GeneralException('请输入取件码', 422);
        }
        $redis_key = sprintf('GET_TAKE_CODE_V1_%d_%s', $service_id, date("Ymd", time()));
        if (!Redis::exists($redis_key)) {
            $res = [];
            array_push($res, $take_code);
            Redis::setex($redis_key, self::REDIS_EXPIRES_FOR_DAY, json_encode($res));
        } else {
            $res = json_decode(Redis::get($redis_key));
            if (in_array($take_code, $res)) {
                throw new GeneralException('该取件码已被使用', 403);
            } else {
                array_push($res, $take_code);
                Redis::setex($redis_key, self::REDIS_EXPIRES_FOR_DAY, json_encode($res));
            }
        }
        DB::beginTransaction();
        try {
            if ($type === false || $type == 1) {
                //自提订单
                $type = 1;
                $shipper_id = 0; //默认订单信息，自提没有
                $status = 1;//入库
                //创建订单
                $create_order = [
                    'order_id' => $this->getOrderId($type),
                    'single_number' => $request->single_number ? $request->single_number : null,
                    'to_mobile' => $request->to_mobile ? $request->to_mobile : null,
                    'take_code' => $take_code,
                    'courier_id' => $courier_id,
                    'express_id' => $express_id,
                    'service_id' => $service_id,
                    'shipper_id' => $shipper_id,
                    'network_id' => $network_id,
                    'type' => $type,
                    'status' => $status,
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now(),
                ];
                $order_id = DB::table('order')->insertGetId($create_order);
                //创建订单信息
                DB::table('order_info')->insert([
                    'order_id' => $order_id,
                    'price' => $unit_price,
                    'platform_money' => self::CHARGE,
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now(),
                ]);
            } else {
                //派送件
                $type = 0;
                $shipper_id = 0; //默认订单信息，自提没有
                $status = 1;//入库
                //创建订单
                $create_order = [
                    'order_id' => $this->getOrderId($type),
                    'single_number' => $request->single_number ? $request->single_number : null,
                    'to_mobile' => $request->to_mobile ? $request->to_mobile : null,
                    'take_code' => $take_code,
                    'courier_id' => $courier_id,
                    'express_id' => $express_id,
                    'service_id' => $service_id,
                    'shipper_id' => $shipper_id,
                    'network_id' => $network_id,
                    'type' => $type,
                    'status' => $status,
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now(),
                ];
                $order_id = DB::table('order')->insertGetId($create_order);
                //创建订单信息
                DB::table('order_info')->insert([
                    'order_id' => $order_id,
                    'price' => $unit_price,
                    'platform_money' => self::CHARGE,
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now(),
                ]);
            }
            //快递员入库数+1  站点入库数+1
            $courier = Courier::where('id', '=', $courier_id)->first();
            $courier->delivery_num += 1;
            $courier->save();
            $service = Service::where('id', '=', $service_id)->first();
            $service->delivery_num += 1;
            $service->save();
            $network = Network::where('id', '=', $network_id)->first();
            $network->delivery_sum += 1;
            $network->save();
            $network_express = NetworkExpress::where('service_id', '=', $service_id)->where('network_id', '=', $network_id)->first();
            if ($network_express) {
                $network_express->total_entry += 1;
                $network_express->save();
            } else {
                throw new GeneralException('合作网点已经解除，无法入库！', 403);
            }

            //生成入库流水
            $tally = new EntryTally;
            $tally->order_id = $order_id;
            $tally->courier_id = (int)$courier_id;
            $tally->express_id = $express_id;
            $tally->service_id = $service_id;
            $tally->network_id = $network_id;
            $tally->unit_price = $unit_price;
            $tally->type = $type;
            $tally->save();
            //生成会员
            $user = User::query()
                ->where('phone', '=', $request->to_mobile)
                ->first();
            if (!$user) {
                $user = new User;
                $user->name = '共派小伙伴' . substr($request->to_mobile, -4);
                $user->phone = $request->to_mobile;
                $user->service_id = $service_id;
                $user->reg_type = 1;
                $user->save();
            }
            //生成日志
            $userLogRepository = new UserLogRepository;
            $operation = '创建了订单[' . $order_id . ']';
            $history = $actuality = null;
            $ip = $request->getClientIp();
            $type = 0;
            $userLogRepository->myLog($courier_id, $service_id, $name, $operation, $history, $actuality, $order_id, $ip, $type);

            //生成返回结果
            DB::commit();
            $res = $this->getOrderDetails($order_id);
            return $res;
        } catch (\Illuminate\Database\QueryException $ex) {
            DB::rollback();
            throw new GeneralException('未知错误', 500);
        }
    }

    /**
     * 生成订单
     * Date: 2018/07/03
     * @author Tenny
     * @param $request
     * @param $type
     * @return \Illuminate\Database\Eloquent\Collection|static[]
     * @throws \App\Exceptions\GeneralException
     */
    public function addOrder_v2($request, $type = false)
    {
        $user = Auth::guard('courier')->user();
        $name = $user->name;
        $service_id = $user->service_id;
        $courier_id = $user->id;
        //判断该快递号是否已经入库
        $result = Order::where('single_number', '=', $request->single_number)
            ->where('status', '!=', 7)
            ->first();
        if ($result) {
            throw new GeneralException('该快递已入库', 400);
        }
        if ($request->single_number) {
            $result = $this->matchingNetwork($service_id, $request->single_number);
        }
        if (is_array($result) && count($result) > 0) {
            $express_id = $result['express_id'];
            $unit_price = $result['unit_price'];
            $network_id = $result['network_id'];
        } else {
            throw new GeneralException('未匹配到合作网点', 400);
        }
        $take_code = $request->take_code ? $request->take_code : null;
        if (!$take_code) {
            throw new GeneralException('请输入取件码', 422);
        }
        $redis_key = sprintf('GET_TAKE_CODE_V1_%d_%s', $service_id, date("Ymd", time()));
        if (!Redis::exists($redis_key)) {
            $res = [];
            array_push($res, $take_code);
            Redis::setex($redis_key, self::REDIS_EXPIRES_FOR_DAY, json_encode($res));
        } else {
            $res = json_decode(Redis::get($redis_key));
            if (in_array($take_code, $res)) {
                throw new GeneralException('该取件码已被使用', 403);
            } else {
                array_push($res, $take_code);
                Redis::setex($redis_key, self::REDIS_EXPIRES_FOR_DAY, json_encode($res));
            }
        }
        DB::beginTransaction();
        try {
            if ($type === false || $type == 1) {
                //自提订单
                $type = 1;
                $shipper_id = 0; //默认订单信息，自提没有
                $status = 3;//待自提
                //创建订单
                $create_order = [
                    'order_id' => $this->getOrderId($type),
                    'single_number' => $request->single_number ? $request->single_number : null,
                    'to_mobile' => $request->to_mobile ? $request->to_mobile : null,
                    'take_code' => $take_code,
                    //'courier_id' => $courier_id,
                    'express_id' => $express_id,
                    'service_id' => $service_id,
                    'shipper_id' => $shipper_id,
                    'network_id' => $network_id,
                    'type' => $type,
                    'status' => $status,
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now(),
                ];
                $order_id = DB::table('order')->insertGetId($create_order);
                //创建订单信息
                DB::table('order_info')->insert([
                    'order_id' => $order_id,
                    'price' => $unit_price,
                    'platform_money' => self::CHARGE,
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now(),
                ]);
                //发送短信
                $message = new Message();
                $service = Service::query()->where('id', '=', $service_id)->first();
                $data = [
                    'take_code' => $take_code,
                    'service_name' => $service->designation,
                    'end_time' => $service->end_time,
                    'phone' => $service->phone,
                ];
                $response = $message->takeMessage($request->to_mobile, $data);
                if (!isset($response['SubmitResult']['code']) || $response['SubmitResult']['code'] != 2) {
                    throw new GeneralException('发送短信失败', 500);
                }
            } else {
                //派送件
                $type = 0;
                $shipper_id = 0; //默认订单信息，自提没有
                $status = 2;//配送中
                //创建订单
                $create_order = [
                    'order_id' => $this->getOrderId($type),
                    'single_number' => $request->single_number ? $request->single_number : null,
                    'to_mobile' => $request->to_mobile ? $request->to_mobile : null,
                    'take_code' => $take_code,
                    'courier_id' => $courier_id,
                    'express_id' => $express_id,
                    'service_id' => $service_id,
                    'shipper_id' => $shipper_id,
                    'network_id' => $network_id,
                    'type' => $type,
                    'status' => $status,
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now(),
                ];
                $order_id = DB::table('order')->insertGetId($create_order);
                //创建订单信息
                DB::table('order_info')->insert([
                    'order_id' => $order_id,
                    'price' => $unit_price,
                    'platform_money' => self::CHARGE,
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now(),
                ]);
            }
            //快递员入库数+1  站点入库数+1
            $courier = Courier::where('id', '=', $courier_id)->first();
            $courier->delivery_num += 1;
            $courier->save();
            $service = Service::where('id', '=', $service_id)->first();
            $service->delivery_num += 1;
            $service->save();
            $network = Network::where('id', '=', $network_id)->first();
            $network->delivery_sum += 1;
            $network->save();
            $network_express = NetworkExpress::where('service_id', '=', $service_id)->where('network_id', '=', $network_id)->orderBy('id', 'desc')->first();
            if ($network_express) {
                $network_express->total_entry += 1;
                $network_express->save();
            } else {
                throw new GeneralException('合作网点已经解除，无法入库！', 403);
            }

            //生成入库流水
            $tally = new EntryTally;
            $tally->order_id = $order_id;
            $tally->courier_id = (int)$courier_id;
            $tally->express_id = $express_id;
            $tally->service_id = $service_id;
            $tally->network_id = $network_id;
            $tally->unit_price = $unit_price;
            $tally->type = $type;
            $tally->save();
            //生成会员
            $user = User::query()
                ->where('phone', '=', $request->to_mobile)
                ->first();
            if (!$user) {
                $user = new User;
                $user->name = '共派小伙伴' . substr($request->to_mobile, -4);
                $user->phone = $request->to_mobile;
                $user->service_id = $service_id;
                $user->reg_type = 1;
                $user->save();
            }
            //生成日志
            $userLogRepository = new UserLogRepository;
            $operation = '创建了订单[' . $order_id . ']';
            $history = $actuality = null;
            $ip = $request->getClientIp();
            $type = 0;
            $userLogRepository->myLog($courier_id, $service_id, $name, $operation, $history, $actuality, $order_id, $ip, $type);

            //生成返回结果
            DB::commit();
            $res = $this->getOrderDetails($order_id);
            return $res;
        } catch (\Illuminate\Database\QueryException $ex) {
            DB::rollback();
            throw new GeneralException('未知错误', 500);
        }
    }

    /**
     * 后台生成订单
     * Date: 2018/05/27
     * @author Tenny
     * @param $request
     * @return \Illuminate\Database\Eloquent\Collection|static[]
     * @throws \App\Exceptions\GeneralException
     */
    public function adminAddOrder($request)
    {
        $user = Auth::guard('station')->user();
        $name = $user->name;
        $service_id = $user->service_id;
        $courier_id = $request->courier_id;
        //判断该快递号是否已经入库
        $result = Order::where('single_number', '=', $request->single_number)
            ->where('status', '!=', 7)
            ->first();
        if ($result) {
            throw new GeneralException('该快递已入库', 400);
        }
        if ($request->single_number) {
            $result = $this->matchingNetwork($service_id, $request->single_number);
        }
        if (is_array($result) && count($result) > 0) {
            $express_id = $result['express_id'];
            $unit_price = $result['unit_price'];
            $network_id = $result['network_id'];
        } else {
            throw new GeneralException('未匹配到合作网点', 400);
        }
        $redis_key = sprintf('GET_TAKE_CODE_V1_%d_%s', $service_id, date("Ymd", time()));
        if (!Redis::exists($redis_key)) {
            $res = [];
            $take_code = date('d', time()) . '0001';
            array_push($res, $take_code);
            Redis::setex($redis_key, self::REDIS_EXPIRES_FOR_DAY, json_encode($res));
        } else {
            $res = json_decode(Redis::get($redis_key));
            $max = max($res);
            $num = substr($max, -4);
            $new_num = substr($num + 1, -4);
            $num_last = str_pad($new_num, 4, '0', STR_PAD_LEFT);
            $take_code = date('d', time()) . $num_last;
            array_push($res, $take_code);
            Redis::setex($redis_key, self::REDIS_EXPIRES_FOR_DAY, json_encode($res));
        }
        DB::beginTransaction();
        try {
            $shipper_id = 0; //默认订单信息，自提没有
            $type = $request->type;
            if ($type == 1) {
                $status = 3;//代取件
                $create_order['courier_id'] = null;
            } else {
                $status = 2;//配送中
                $create_order['courier_id'] = $courier_id;
            }
            $label = $request->region_mark ? $request->region_mark : null;
            $region_mark = $request->region_mark ? $request->region_mark : null;
            if ($label) {
                if ((FALSE !== stripos($label, '拒收')) || (FALSE !== stripos($label, '错分'))) {
                    $status = 6;
                }
            }
            //创建订单
            $create_order = [
                'order_id' => $this->getOrderId($type),
                'single_number' => $request->single_number ? $request->single_number : null,
                'to_mobile' => $request->to_mobile ? $request->to_mobile : null,
                'take_code' => $take_code,
                'express_id' => $express_id,
                'service_id' => $service_id,
                'shipper_id' => $shipper_id,
                'network_id' => $network_id,
                'label' => $label,
                'type' => $type,
                'status' => $status,
                'created_at' => Carbon::now(),
                'updated_at' => Carbon::now(),
            ];
            $order_id = DB::table('order')->insertGetId($create_order);
            //创建订单信息
            $create_order_info = [
                'order_id' => $order_id,
                'price' => $unit_price,
                'platform_money' => self::CHARGE,
                'created_at' => Carbon::now(),
                'updated_at' => Carbon::now(),
            ];
            if ($region_mark) {
                $create_order_info['region_mark'] = $region_mark;
            }
            DB::table('order_info')->insert($create_order_info);
            //快递员入库数+1  站点入库数+1
            $service = Service::where('id', '=', $service_id)->first();
            $service->delivery_num += 1;
            $service->save();
            $network = Network::where('id', '=', $network_id)->first();
            $network->delivery_sum += 1;
            $network->save();
            $network_express = NetworkExpress::where('service_id', '=', $service_id)->where('network_id', '=', $network_id)->first();
            if ($network_express) {
                $network_express->total_entry += 1;
                $network_express->save();
            } else {
                throw new GeneralException('合作网点已经解除，无法入库！', 403);
            }
            //生成入库流水
            $tally = new EntryTally;
            $tally->order_id = $order_id;
            $tally->courier_id = (int)$courier_id;
            $tally->express_id = $express_id;
            $tally->service_id = $service_id;
            $tally->network_id = $network_id;
            $tally->unit_price = $unit_price;
            $tally->type = $type;
            $tally->save();
            //生成会员
            $user = User::query()
                ->where('phone', '=', $request->to_mobile)
                ->first();
            if (!$user) {
                $user = new User;
                $user->name = '共派小伙伴' . substr($request->to_mobile, -4);
                $user->phone = $request->to_mobile;
                $user->service_id = $service_id;
                $user->reg_type = 1;
                $user->save();
            }
            //生成日志
            $userLogRepository = new UserLogRepository;
            $operation = '创建了订单[' . $order_id . ']';
            $history = $actuality = null;
            $ip = $request->getClientIp();
            $type = 3;
            $userLogRepository->myLog($user->id, $service_id, $name, $operation, $history, $actuality, $order_id, $ip, $type);
            //生成返回结果
            DB::commit();
            $res = $this->getOrderDetails($order_id);
            return $res;
        } catch (\Illuminate\Database\QueryException $ex) {
            DB::rollback();
            throw new GeneralException('未知错误', 500);
        }
    }

    /**
     * 快递员出库操作
     * Date: 2018/5/28
     * @author Tenny
     * @param $order_id
     * @param $single_number
     * @param $ip
     * @return \Illuminate\Database\Eloquent\Collection|static[]
     * @throws \App\Exceptions\GeneralException
     * @deprecated 2018/07/03
     */
    public function deliveryOrders($order_id, $single_number, $ip)
    {
        $user = Auth::guard('courier')->user();
        $courier_id = $user->id;
        $service_id = $user->service_id;
        $name = $user->name;
        if ($courier_id == false) {
            throw new GeneralException('请登录', 401);
        }
        if ($order_id) {
            $order = $this->getOrderDetails($order_id);
        } elseif ($single_number) {
            $order = Order::where('single_number', '=', $single_number)->orderBy('id', 'desc')->first();
            if (optional($order)->id) {
                $order_id = $order->id;
            } else {
                throw new GeneralException('请上传正确的快递号', 422);
            }
        } else {
            throw new GeneralException('请上传正确的快递号或者id', 422);
        }
        //判断订单状态 只有缓存中的订单才能进行出库操作 1.暂存  2.配送中，3.待取件，4.已取件，5.投诉中，6.异常件，7.已退回 ，8.已退款
        if (optional($order)->status !== null && $order->status == 1 || $order->status == 6) {
            DB::beginTransaction();
            try {
                //生成收件人信息  0.派送件  1.自提件，2.寄送件
                if ($order->type == 0 || $order->type == 2) {
                    $actuality = json_encode(['info' => '派送中'], true);
                    DB::table('order')
                        ->where('id', $order_id)
                        ->update([
                            'courier_id' => $courier_id,
                            'status' => 2,
                            'updated_at' => Carbon::now(),
                        ]);
                } else {
                    $actuality = json_encode(['info' => '代取件'], true);
                    DB::table('order')
                        ->where('id', $order_id)
                        ->update([
                            'courier_id' => $courier_id,
                            'status' => 3,
                            'updated_at' => Carbon::now(),
                        ]);
                }
                //生成日志
                $userLogRepository = new UserLogRepository;
                $operation = '出库[' . $order->id . ']';
                $history = json_encode(['info' => self::ORDER_STATUS[$order->status]], true);
                $type = 0;
                $userLogRepository->myLog($courier_id, $service_id, $name, $operation, $history, $actuality, $order_id, $ip, $type);

                //生成返回结果
                DB::commit();
                //删除订单详情缓存
                $redis_key = sprintf('GET_ORDER_DETAILS_V1_%d', $order_id);
                Redis::del($redis_key);
                //$res = $this->getOrderDetails($order_id);
                $res = [];
                return $res;
            } catch (\Illuminate\Database\QueryException $ex) {
                DB::rollback();
                throw new GeneralException('未知错误', 500);
            }
        } else {
            throw new GeneralException('订单已出库', 403);
        }
    }

    /**
     * 管理员出库操作
     * Date: 2018/5/28
     * @author Tenny
     * @param $request
     * @return \Illuminate\Database\Eloquent\Collection|static[]
     * @throws \App\Exceptions\GeneralException
     */
    public function adminDeliveryOrders($request)
    {
        $user = Auth::guard('station')->user();
        $admin_id = $user->id;
        $service_id = $user->service_id;
        $name = $user->name;
        $ip = $request->getClientIp();
        $single_number = $request->single_number ? $request->single_number : null;
        if ($single_number) {
            $order = Order::where('single_number', '=', $single_number)->orderBy('id', 'desc')->first();
            if (optional($order)->id) {
                $order_id = $order->id;
            } else {
                throw new GeneralException('请上传正确的快递号', 422);
            }
        } else {
            throw new GeneralException('请上传正确的快递号', 422);
        }
        //判断订单状态 只有缓存中的订单才能进行出库操作 1.暂存  2.配送中，3.待取件，4.已取件，5.投诉中，6.异常件，7.已退回 ，8.已退款
        if (optional($order)->status !== null && ($order->status == 2 || $order->status == 3 || $order->status == 7)) {
            DB::beginTransaction();
            try {
                //生成收件人信息  0.派送件  1.自提件，2.寄送件
                if ($order->type == 0 || $order->type == 2) {
                    $actuality = json_encode(['info' => '派送中'], true);
                    DB::table('order')
                        ->where('id', $order_id)
                        ->update([
                            'status' => 2,
                            'updated_at' => Carbon::now(),
                        ]);
                } else if ($order->type == 1) {
                    $actuality = json_encode(['info' => '代取件'], true);
                    DB::table('order')
                        ->where('id', $order_id)
                        ->update([
                            'status' => 3,
                            'updated_at' => Carbon::now(),
                        ]);
                }
                $order_info = OrderInfo::where('order_id', '=', $order->id)->orderBy('id', 'desc')->first();
                //生成出库流水
                $tally = new SignOutTally;
                $tally->order_id = $order_id;
                $tally->courier_id = 0;
                $tally->express_id = $order->express_id;
                $tally->service_id = $service_id;
                $tally->network_id = $order->network_id;
                $tally->unit_price = round($order_info->price, 2);
                $tally->status = 0;
                $tally->type = $order->type;
                $tally->save();
                //生成出库流水
                $date = date("Y-m-d", time());
                $bills = Bills::query()
                    ->where('date', '=', $date)
                    ->where('service_id', '=', $order->service_id)
                    ->where('network_id', '=', $order->network_id)
                    ->first();
                if ($bills) {
                    $bills->total_sign += 1;
                    $bills->total_income = round($bills->total_income + $order_info->price, 2);
                    $bills->save();
                } else {
                    $bills = new Bills;
                    $bills->date = $date;
                    $bills->service_id = $order->service_id;
                    $bills->network_id = $order->network_id;
                    $bills->total_sign = 1;
                    $bills->total_income = $order_info->price;
                    $bills->save();
                }
                //生成日志
                $userLogRepository = new UserLogRepository;
                $operation = '出库[' . $order->id . ']';
                $history = json_encode(['info' => self::ORDER_STATUS[$order->status]], true);
                $type = 3;
                $userLogRepository->myLog($admin_id, $service_id, $name, $operation, $history, $actuality, $order_id, $ip, $type);

                //生成返回结果
                DB::commit();
                //删除订单详情缓存
                $redis_key = sprintf('GET_ORDER_DETAILS_V1_%d', $order_id);
                Redis::del($redis_key);
                //$res = $this->getOrderDetails($order_id);
                $res = [];
                return $res;
            } catch (\Illuminate\Database\QueryException $ex) {
                DB::rollback();
                throw new GeneralException('未知错误', 500);
            }
        } else {
            throw new GeneralException('订单已出库', 403);
        }
    }

    /**
     * 今日出库数据
     * Date: 2018/07/03
     * @author Tenny
     * @param $limit
     * @param $type
     * @return mixed
     */
    public function deliveryData($limit = false, $type = false)
    {
        $user = Auth::guard('station')->user();
        $service_id = $user->service_id;
        $query = SignOutTally::query();
        $query
            ->select(['order.single_number', 'order.take_code', 'order.to_mobile', 'sign_out_tally.created_at'])
            ->leftJoin('order', 'order.id', '=', 'sign_out_tally.order_id')
            ->where('order.service_id', '=', $service_id)
            ->where('sign_out_tally.status', '=', 0)
            ->where('sign_out_tally.type', '=', 1)
            ->orderBy('order.created_at', 'desc')
            ->whereBetween('sign_out_tally.created_at', [
                date("Y-m-d 00:00:00", time()),
                date("Y-m-d 23:59:59", time())
            ]);
        if ($type) {
            return $query->count();
        } else {
            if ($limit === false) {
                return $query->get();
            } else {
                return $query->paginate($limit);
            }
        }
    }

    /**
     * 标签操作
     * Date: 2018/5/28
     * @author Tenny
     * @param $order_id
     * @param $sign
     * @param $ip
     * @param $region_mark
     * @return \Illuminate\Database\Eloquent\Collection|static[]
     * @throws \App\Exceptions\GeneralException
     */
    public function doSign($order_id, $sign, $ip, $region_mark)
    {
        $user = Auth::guard('courier')->user();
        $courier_id = $user->id;
        $service_id = $user->service_id;
        $name = $user->name;
        if ($sign == false) {
            throw new GeneralException('请上传标签内容', 401);
        }
        if ($order_id == false) {
            throw new GeneralException('请上传正确的订单号', 422);
        }
        $order = $this->getOrderDetails($order_id);
        /*
           代收货款 - 对应前端的代收货款，操作后快件状态不变
           污染 - 对应前端的污染，操作后快件状态不变
           破损 – 对应前端的破损，操作后快件状态不变
           拒收 – 对应前端的拒收，操作后快件状态改变为异常件
           错分 – 对应前端的错分，操作后快件状态改变为异常件
           地址变更 – 对应前端的地址变更，操作后快件状态不变
       */
        DB::beginTransaction();
        try {
            //拒收  错分修改订单状态为异常件
            if ((FALSE !== stripos($sign, '拒收')) || (FALSE !== stripos($sign, '错分'))) {
                if (optional($order)->status && $order->status == 4) {
                    //生成出库流水
                    $tally = new SignOutTally();
                    $tally->order_id = $order_id;
                    $tally->courier_id = $courier_id;
                    $tally->express_id = $order->express_id;
                    $tally->service_id = $service_id;
                    $tally->network_id = (int)$order->network_id;
                    $tally->unit_price = (int)$order->unit_price;
                    $tally->status = 1;
                    $tally->type = $order->type;
                    $tally->save();
                }
                DB::table('order')
                    ->where('id', $order_id)
                    ->update([
                        'status' => 6,
                        'label' => $sign,
                        'updated_at' => Carbon::now(),
                    ]);
            } else {
                DB::table('order')
                    ->where('id', $order_id)
                    ->update([
                        'label' => $sign,
                        'updated_at' => Carbon::now(),
                    ]);
            }
            if ($region_mark != false) {
                DB::table('order_info')
                    ->where('order_id', $order_id)
                    ->update([
                        'region_mark' => $region_mark,
                        'updated_at' => Carbon::now(),
                    ]);
            }
            //生成日志
            $userLogRepository = new UserLogRepository;
            $operation = '为[' . $order->id . ']标记了[' . $sign . ']';
            $history = $actuality = null;
            $type = 0;
            $userLogRepository->myLog($courier_id, $service_id, $name, $operation, $history, $actuality, $order_id, $ip, $type);

            //生成返回结果
            DB::commit();
            //删除订单详情缓存
            $redis_key = sprintf('GET_ORDER_DETAILS_V1_%d', $order_id);
            Redis::del($redis_key);
            //$res = $this->getOrderDetails($order_id);
            $res = [];
            return $res;
        } catch (\Illuminate\Database\QueryException $ex) {
            DB::rollback();
            throw new GeneralException('未知错误', 500);
        }
    }

    /**
     * 派送操作
     * Date: 2018/5/28
     * @author Tenny
     * @param $order_id
     * @param $single_number
     * @param $ip
     * @return \Illuminate\Database\Eloquent\Collection|static[]
     * @throws \App\Exceptions\GeneralException
     */
    public function doSend($order_id, $single_number, $ip)
    {
        $user = Auth::guard('courier')->user();
        $courier_id = $user->id;
        $service_id = $user->service_id;
        $name = $user->name;
        if ($order_id) {
            $order = $this->getOrderDetails($order_id);
        } elseif ($single_number) {
            $order = Order::where('single_number', '=', $single_number)->orderBy('id', 'desc')->first();
            if (!optional($order)->id) {
                throw new GeneralException('请上传正确的快递号', 422);
            }
            $order_id = $order->id;
        } else {
            throw new GeneralException('请上传正确的快递号或者id', 422);
        }
        if ($order->type != 1 || ($order->type == 1 && $order->status != 3)) {
            throw new GeneralException('该订单不是自提订单', 422);
        }
        if ($order->service_id != $service_id) {
            throw new GeneralException('该快件不是本站点的', 403);
        }
        DB::beginTransaction();
        try {
            if ($order_id) {
                DB::table('order')
                    ->where('id', $order_id)
                    ->update([
                        'courier_id' => $courier_id,
                        'status' => 2,
                        'type' => 0,
                        'updated_at' => Carbon::now(),
                    ]);
                //修改入库流水
                EntryTally::query()
                    ->where('order_id', '=', $order_id)
                    ->orderBy('id', 'desc')
                    ->first()
                    ->update(['type' => 0]);
            }

            //生成日志
            $userLogRepository = new UserLogRepository;
            $operation = '对[' . $order->id . ']进行了派送操作';
            $history = json_encode(['info' => self::ORDER_STATUS[$order->status]], true);
            $type = 0;
            $actuality = json_encode(['info' => '派送中'], true);
            $userLogRepository->myLog($courier_id, $service_id, $name, $operation, $history, $actuality, $order_id, $ip, $type);

            //生成返回结果
            DB::commit();
            //删除订单详情缓存
            $redis_key = sprintf('GET_ORDER_DETAILS_V1_%d', $order_id);
            Redis::del($redis_key);
            //$res = $this->getOrderDetails($order_id);
            $res = [];
            return $res;
        } catch (\Illuminate\Database\QueryException $ex) {
            DB::rollback();
            throw new GeneralException('未知错误', 500);
        }
    }

    /**
     * 签收操作
     * Date: 2018/5/28
     * @author Tenny
     * @param $order_id
     * @param $single_number
     * @param $ip
     * @return \Illuminate\Database\Eloquent\Collection|static[]
     * @throws \App\Exceptions\GeneralException
     */
    public function doSigning($order_id, $single_number, $ip)
    {
        $user = Auth::guard('courier')->user();
        $courier_id = $user->id;
        $service_id = $user->service_id;
        $name = $user->name;
        if ($single_number) {
            $order = Order::where('single_number', '=', $single_number)->orderBy('id', 'desc')->first();
            if (!optional($order)->id) {
                throw new GeneralException('未找到该资源！请刷新页面', 404);
            } else {
                $order_id = $order->id;
            }
        }
        if ($order_id == false) {
            throw new GeneralException('未找到该资源！请刷新页面', 404);
        }
        $order = $this->getOrderDetails($order_id);
        if (!$order) {
            throw new GeneralException('找不到该资源！请刷新页面', 403);
        }
        if (optional($order)->status && $order->status == 4) {
            throw new GeneralException('您已签收过了！', 403);
        }
        if (!in_array($order->status, ['1', '2', '3'])) {
            throw new GeneralException('该订单不能出库！', 403);
        }
        DB::beginTransaction();
        try {
            DB::table('order')
                ->where('id', $order_id)
                ->update([
                    'courier_id' => $courier_id,
                    'status' => 4,
                    'sign_in_at' => Carbon::now(),
                    'updated_at' => Carbon::now(),
                ]);
            $order_info = OrderInfo::where('order_id', '=', $order->id)->orderBy('id', 'desc')->first();
            if (!$order_info) {
                throw new GeneralException('订单异常', 400);
            }
            //快递员出库数+1  站点出库数+1
            $courier = Courier::where('id', '=', $courier_id)->first();
            $courier->send_num += 1;
            $courier->save();
            $service = Service::where('id', '=', $service_id)->first();
            $service->send_num += 1;
            $service->total_income = round($service->total_income + $order_info->price, 2);
            $service->save();
            $network = Network::where('id', '=', $order->network_id)->first();
            $network->send_sum += 1;
            $network->save();
            $network_express = NetworkExpress::where('service_id', '=', $order->service_id)->where('network_id', '=', $order->network_id)->first();
            if ($network_express) {
                $network_express->total_sign += 1;
                $network_express->total = round($network_express->total + $order_info->price, 2);
                $network_express->save();
            }
            //生成出库流水
            $tally = new SignOutTally;
            $tally->order_id = $order_id;
            $tally->courier_id = $courier_id;
            $tally->express_id = $order->express_id;
            $tally->service_id = $service_id;
            $tally->network_id = $order->network_id;
            $tally->unit_price = round($order_info->price, 2);
            $tally->status = 0;
            $tally->type = $order->type;
            $tally->save();
            //生成出库流水
            $date = date("Y-m-d", time());
            $bills = Bills::query()
                ->where('date', '=', $date)
                ->where('service_id', '=', $order->service_id)
                ->where('network_id', '=', $order->network_id)
                ->first();
            if ($bills) {
                $bills->total_sign += 1;
                $bills->total_income = round($bills->total_income + $order_info->price, 2);
                $bills->save();
            } else {
                $bills = new Bills;
                $bills->date = $date;
                $bills->service_id = $order->service_id;
                $bills->network_id = $order->network_id;
                $bills->total_sign = 1;
                $bills->total_income = $order_info->price;
                $bills->save();
            }
            //生成日志
            $userLogRepository = new UserLogRepository;
            $operation = '操作了 签收快件[' . $order->id . ']';
            $history = json_encode(['info' => self::ORDER_STATUS[$order->status]], true);
            $actuality = json_encode(['info' => '已收件'], true);
            $type = 0;
            $userLogRepository->myLog($courier_id, $service_id, $name, $operation, $history, $actuality, $order_id, $ip, $type);

            //生成返回结果
            DB::commit();
            //删除订单详情缓存
            $redis_key = sprintf('GET_ORDER_DETAILS_V1_%d', $order_id);
            Redis::del($redis_key);
            //$res = $this->getOrderDetails($order_id);
            $res = [];
            return $res;
        } catch (\Illuminate\Database\QueryException $ex) {
            DB::rollback();
            throw new GeneralException('未知错误', 500);
        }
    }

    /**
     * 获取服务站子站点列表
     * Date: 2018/06/14
     * @param $service_id
     * @author Tenny
     * @return \Illuminate\Database\Eloquent\Collection|static[]
     */
    public function getServices($service_id = false)
    {
        $query = Service::query();
        if ($service_id !== false) {
            $query->where(function ($query) use ($service_id) {
                $query->where('id', '=', $service_id)
                    ->orWhere('pid', '=', $service_id);
            });
        }
        $services = $query
            ->select(['id', 'designation', 'is_child', 'address'])
            ->orderBy('id')
            ->get();
        return $services;
    }

    /**
     * 退回网点操作
     * Date: 2018/5/28
     * @author Tenny
     * @param $request
     * @return \Illuminate\Database\Eloquent\Collection|static[]
     * @throws \App\Exceptions\GeneralException
     */
    public function retreat($request)
    {
        $user = Auth::guard('station')->user();
        $admin_id = $user->id;
        $service_id = $user->service_id;
        $name = $user->name;
        $ip = $request->getClientIp();
        $single_number = $request->single_number ? $request->single_number : null;
        if ($single_number) {
            $order = Order::with('info')
                ->where('single_number', '=', $single_number)
                ->orderBy('id', 'desc')
                ->first();
            if (optional($order)->id) {
                $order_id = $order->id;
            } else {
                throw new GeneralException('请上传正确的快递号', 422);
            }
        } else {
            throw new GeneralException('请上传正确的快递号', 422);
        }
        $order_info = OrderInfo::where('order_id', '=', $order_id)->orderBy('id', 'desc')->first();
        //判断订单状态 只有缓存中的订单才能进行出库操作 1.暂存  2.配送中，3.待取件，4.已取件，5.投诉中，6.异常件，7.已退回 ，8.已退款
        if (optional($order)->status && $order->status == 6) {
            DB::beginTransaction();
            try {
                DB::table('order')
                    ->where('id', $order_id)
                    ->update([
                        'status' => 7,
                        'updated_at' => Carbon::now(),
                    ]);
                /*
                 *  生成出库流水
                 *  先查询流水是否存在  存在就添加一条退回网点流水  不存在添加一条0单价的流水
                 * */
                $sign_out_tally = SignOutTally::query()
                    ->where('order_id', '=', $order_id)
                    ->where('status', '=', 0)
                    ->orderBy('created_at', 'desc')
                    ->first();
                $is_out = false;
                if ($sign_out_tally) {
                    $tally = new SignOutTally;
                    $tally->order_id = $order_id;
                    $tally->courier_id = $order->courier_id;
                    $tally->express_id = $order->express_id;
                    $tally->service_id = $service_id;
                    $tally->network_id = $order->network_id;
                    $tally->unit_price = round($order_info->price, 2);
                    $tally->status = 1;
                    $tally->type = $order->type;
                    $tally->save();
                    $is_out = true;
                } else {
                    $tally = new SignOutTally;
                    $tally->order_id = $order_id;
                    $tally->courier_id = $order->courier_id;
                    $tally->express_id = $order->express_id;
                    $tally->service_id = $service_id;
                    $tally->network_id = $order->network_id;
                    $tally->unit_price = 0.00;
                    $tally->status = 1;
                    $tally->type = $order->type;
                    $tally->save();
                }
                //生成出库流水账单
                if ($is_out) {
                    $date = date("Y-m-d", time());
                    $bills = Bills::query()
                        ->where('date', '=', $date)
                        ->where('service_id', '=', $order->service_id)
                        ->where('network_id', '=', $order->network_id)
                        ->first();
                    if ($bills) {
                        $bills->total_sign -= 1;
                        $bills->total_income = round($bills->total_income - $order_info->price, 2);
                        $bills->save();
                    } else {
                        $bills = new Bills;
                        $bills->date = $date;
                        $bills->service_id = $order->service_id;
                        $bills->network_id = $order->network_id;
                        $bills->total_sign = -1;
                        $bills->total_income = -round($order_info->price, 2);
                        $bills->save();
                    }
                }
                //生成日志
                $userLogRepository = new UserLogRepository;
                $operation = '把快件[' . $order->id . ']退回了网点';
                $history = $actuality = null;
                $type = 3;
                $userLogRepository->myLog($admin_id, $service_id, $name, $operation, $history, $actuality, $order_id, $ip, $type);

                //生成返回结果
                DB::commit();
                //删除订单详情缓存
                $redis_key = sprintf('GET_ORDER_DETAILS_V1_%d', $order_id);
                Redis::del($redis_key);
                $res = [];
                return $res;
            } catch (\Illuminate\Database\QueryException $ex) {
                DB::rollback();
                throw new GeneralException('未知错误', 500);
            }
        } else {
            throw new GeneralException('未查询到该订单', 403);
        }
    }

    /**
     * 今日退回网点数据
     * Date: 2018/07/03
     * @author Tenny
     * @param $limit
     * @param $type
     * @return mixed
     */
    public function retreatData($limit = false, $type = false)
    {
        $user = Auth::guard('station')->user();
        $service_id = $user->service_id;
        $query = SignOutTally::query();
        $query
            ->select(['order.single_number', 'network.designation as network_name', 'order.to_mobile', 'sign_out_tally.created_at'])
            ->leftJoin('order', 'order.id', '=', 'sign_out_tally.order_id')
            ->leftJoin('network', 'network.id', '=', 'sign_out_tally.network_id')
            ->where('order.service_id', '=', $service_id)
            ->where('sign_out_tally.status', '=', 1)
            ->orderBy('order.created_at', 'desc')
            ->whereBetween('sign_out_tally.created_at', [
                date("Y-m-d 00:00:00", time()),
                date("Y-m-d 23:59:59", time())
            ]);
        if ($type) {
            return $query->count();
        } else {
            if ($limit === false) {
                return $query->get();
            } else {
                return $query->paginate($limit);
            }
        }
    }

    /**
     * 获取网点的快递公司
     * Date: 2018/5/28
     * @author Tenny
     * @param $service_id
     * @return \Illuminate\Database\Eloquent\Collection|static[]
     */
    public function getServiceExpress($service_id)
    {
        $result = null;
        if (!$service_id) {
            return $result;
        }
        $query = Service::query();
        $result = $query
            ->select(['service.id as service_id', 'service.designation as service_name', 'network.id as network_id', 'express_company.id as express_id', 'network.designation as network_name', 'network_express.id as relation_id', 'network_express.unit_price', 'express_company.express_name', 'express_company.express_no', 'express_company.code_name'])
            ->leftJoin('network_express', 'network_express.service_id', '=', 'service.id')
            ->leftJoin('network', 'network_express.network_id', '=', 'network.id')
            ->leftJoin('express_company', 'express_company.id', '=', 'network.express_id')
            ->where('service.id', $service_id)
            ->get()
            ->toArray();
        return $result;
    }

    /**
     * 根据快递公司名称匹配网点
     * Date: 2018/06/28
     * @author Tenny
     * @param $service_id
     * @param $single_number
     * @return \Illuminate\Database\Eloquent\Collection|static[]
     * @throws \App\Exceptions\GeneralException
     */
    public function matchingNetwork($service_id, $single_number)
    {
        $result = [];
        $express_info = $this->getExpress($single_number);
        if (is_array($express_info) && count($express_info) > 0) {
            $express_name = $express_info['name'];
        } else {
            return $result;
        }
        $network_list = $this->getServiceExpress($service_id);
        if (is_array($network_list) && count($network_list) > 0) {
            foreach ($network_list as $item) {
                if ($item['code_name'] === $express_name) {
                    $result = $item;
                    break;
                }
            }
        } else {
            return $result;
        }
        return $result;
    }

    /**
     * 获取物流公司
     * Date: 2018/5/28
     * @author Tenny
     * @param $express_id
     * @return \Illuminate\Database\Eloquent\Collection|static[]
     * @throws \App\Exceptions\GeneralException
     */
    public function getExpress($express_id)
    {
        $redis_key = sprintf('GET_ORDER_EXPRESS_V1_%s', $express_id);
        if (!Redis::exists($redis_key)) {
            $express = $this->getLogisticsInfo($express_id);
            if ($express !== false && is_array($express) && count($express) > 0) {
                Redis::setex($redis_key, self::REDIS_EXPIRES_FOR_DAY, json_encode($express));
            }
        } else {
            $res = Redis::get($redis_key);
            $express = (array)json_decode($res);
        }
        if ($express == false || !is_array($express) || count($express) == 0) {
            throw new GeneralException('快递号查询失败', 400);
        }
        $result = config('express.express');
        if (array_key_exists('com', $express) && array_key_exists($express['com'], $result)) {
            $data = [
                'name' => $result[$express['com']],
                'come' => $express['com'],
            ];
            return $data;
        } else {
            throw new GeneralException('查询失败', 400);
        }
    }

    /**
     * 生成订单ID
     * Date: 2018/5/27
     * 【两位字母（订单类型：派送PS 自提ZT 寄送JS）】+【十二位数字（YYMMDDHHmmss）】+【四位数字（自增长）】
     * @param $type 0:派送 1:自提 2:寄送
     * @author Tenny
     * @return string
     */
    public function getOrderId($type = 1)
    {
        $str = '';
        switch ($type) {
            case '0':
                $str .= 'PS';
                break;
            case '1':
                $str .= 'ZT';
                break;
            case '2':
                $str .= 'JS';
                break;
            default:
                $str .= 'ZT';
                break;
        }
        $str .= date('ymdHis', time());
        //随机生成四位自增id
        $redis_key = sprintf('GET_ORDER_NUMBER_V1_%s', date("Ymd", time()));
        if (!Redis::exists($redis_key)) {
            $order_id = 1;
            Redis::setex($redis_key, self::REDIS_EXPIRES_FOR_DAY, json_encode($order_id));
        } else {
            $res = Redis::get($redis_key);
            $order_id = json_decode($res) + 1;
            Redis::setex($redis_key, self::REDIS_EXPIRES_FOR_DAY, json_encode($order_id));
        }
        $str .= str_pad($order_id, 4, '0', STR_PAD_LEFT);
        return $str;
    }

    /**
     * 生成取件码
     * Date: 2018/5/27
     * 【两位日期】+【四位数字（自增长）】
     * @author Tenny
     * @param $service_id
     * @return string
     */
    public function getTakeCode($service_id)
    {
        $redis_key = sprintf('GET_TAKE_CODE_V1_%d_%s', $service_id, date("Ymd", time()));
        if (!Redis::exists($redis_key)) {
            $res = [];
            $take_code = date('d', time()) . '0001';
            array_push($res, $take_code);
            //Redis::setex($redis_key, self::REDIS_EXPIRES_FOR_DAY, json_encode($res));
        } else {
            $res = json_decode(Redis::get($redis_key));
            $max = max($res);
            $num = substr($max, -4);
            $new_num = substr($num + 1, -4);
            $num_last = str_pad($new_num, 4, '0', STR_PAD_LEFT);
            $take_code = date('d', time()) . $num_last;
            /* array_push($res, $take_code);
             Redis::setex($redis_key, self::REDIS_EXPIRES_FOR_DAY, json_encode($res));*/
        }
        return $take_code;
    }

    /**
     * @desc http://www.kuaidi100.com/query?type=zhongtong&postid=453371918456&id=1&valicode=&temp=0.40349807080624434
     * @desc 返回的数据结果参考官方文档：https://www.kuaidi100.com/openapi/api_post.shtml
     * @desc 直接调用该方法,传入物流单号即可查询物流信息
     * @param string $order_no
     * @return bool|mixed
     */
    public function getLogisticsInfo($order_no = '')
    {
        $result = $this->getOrder($order_no);
        $auto_arr = $result['auto'];
        if (count($auto_arr) > 0) {
            foreach ($auto_arr as $key => $value) {
                $temp = $this->randFloat();
                $comCode = $value['comCode'];
                $url = "http://www.kuaidi100.com/query?type=$comCode&postid=$order_no&id=1&valicode=&temp=$temp";// $temp 随机数,防止缓存
                $json = $this->getContent($url);
                $data = json_decode($json, true);
                if ($data['message'] == 'ok') {
                    return $data;
                }
            }
        }
        return false;
    }

    /**
     * @desc 采集网页内容的方法，建议使用curl，效率更高
     * @param $url
     * @return mixed|string
     */
    private function getContent($url)
    {
        $ch = curl_init();
        $timeout = 5;   // 设置5秒超时
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
        $file_contents = curl_exec($ch);
        curl_close($ch);
        return $file_contents;
    }

    /**
     * @desc 得到目前物流单号可能存在的快递公司
     * @param string $order_no
     * @return mixed
     */
    public function getOrder($order_no = '')
    {
        $result = $this->getContent("http://www.kuaidi100.com/autonumber/autoComNum?text=" . $order_no);
        $data = json_decode($result, true);
        return $data;
    }

    /**
     * 生成0~1随机小数
     * @param Int $min
     * @param Int $max
     * @return Float
     */
    public function randFloat($min = 0, $max = 1)
    {
        return $min + mt_rand() / mt_getrandmax() * ($max - $min);
    }

    protected function serialization(array $attributes)
    {
        // TODO: Implement serialization() method.
    }
}